package handler

import (
	"fmt"
	"gitee.com/mangenotwork/game-douniu/api/dao"
	"gitee.com/mangenotwork/game-douniu/api/entity"
	"github.com/mangenotwork/common/conf"
	"github.com/mangenotwork/common/ginHelper"
	"github.com/mangenotwork/common/log"
	"github.com/mangenotwork/common/utils"
	"os"
	"path"
	"strings"
	"sync"
)

func Index(c *ginHelper.GinCtx) {
	poker := entity.NewPoker()

	c.APIOutPut(poker, "ok")
}

// 注册
type RegisterParam struct {
	Account  string `json:"account"`   // 账号
	Password string `json:"password"`  // 密码
	NickName string `json:"nick_name"` // 玩家昵称
}

type RegisterResp struct {
	UserId int64  `json:"user_id"` // 用户id
	Token  string `json:"token"`   // token
	Tip    string `json:"tip"`     // 提示信息
}

func Register(c *ginHelper.GinCtx) {
	param := &RegisterParam{
		Account:  c.GetQuery("account"),
		Password: c.GetQuery("password"),
		NickName: c.GetQuery("nick_name"),
	}

	if len(param.Account) < 1 {
		c.APIOutPutError(fmt.Errorf("账号不能为空"), "账号不能为空")
		return
	}
	if len(param.Password) < 3 {
		c.APIOutPutError(fmt.Errorf("密码不能少于3个字符"), "密码不能少于3个字符")
		return
	}
	if len(param.NickName) < 1 {
		c.APIOutPutError(fmt.Errorf("昵称不能为空"), "昵称不能为空")
		return
	}

	isRepeat := new(dao.UserDao).IsRepeat(param.Account, param.NickName)
	if !isRepeat {
		c.APIOutPut(&RegisterResp{
			Token: "",
			Tip:   "账号或昵称重复，请重新输入",
		}, "ok")
		return
	}

	hostUrl, err := conf.YamlGetString("hostUrl")
	if err != nil {
		c.APIOutPutError(err, err.Error())
		return
	}

	user, err := new(dao.UserDao).Register(&entity.UserBase{
		Account:  param.Account,
		Password: param.Password,
		NickName: param.NickName,
		Avatar:   hostUrl + "/img/default.jpg",
	})

	if err != nil {
		c.APIOutPutError(err, err.Error())
		return
	}

	log.Info(user)

	// 生成token
	j := utils.NewJWT(conf.Conf.Default.Jwt.Secret, conf.Conf.Default.Jwt.Expire)
	j.AddClaims("userId", user.UserId)
	token, tokenErr := j.Token()
	if tokenErr != nil {
		log.Error("生产token错误， err = ", tokenErr)
	}

	c.APIOutPut(&RegisterResp{
		UserId: user.UserId,
		Token:  token,
		Tip:    "创建用户成功",
	}, "ok")
	return
}

func Text(c *ginHelper.GinCtx) {
	c.APIOutPut("ok", "ok")
}

type LoginParam struct {
	Account  string `json:"account"`  // 账号
	Password string `json:"password"` // 密码
}

func Login(c *ginHelper.GinCtx) {
	param := &LoginParam{
		Account:  c.GetQuery("account"),
		Password: c.GetQuery("password"),
	}
	//err := c.GetPostArgs(param)
	//if err != nil {
	//	c.APIOutPutError(err, err.Error())
	//	return
	//}
	user, err := new(dao.UserDao).Login(param.Account, param.Password)
	if err != nil || user.UserId < 1 {
		c.APIOutPut(&RegisterResp{
			Token: "",
			Tip:   "账号不存在",
		}, "ok")
		return
	}
	j := utils.NewJWT(conf.Conf.Default.Jwt.Secret, conf.Conf.Default.Jwt.Expire)
	j.AddClaims("userId", user.UserId)
	token, tokenErr := j.Token()
	if tokenErr != nil {
		log.Error("生产token错误， err = ", tokenErr)
	}

	c.APIOutPut(&RegisterResp{
		UserId: user.UserId,
		Token:  token,
		Tip:    "登录成功",
	}, "ok")
	return
}

type UserInfoData struct {
	UserId    int64  `json:"user_id"`    // 用户id
	Account   string `json:"account"`    // 账号
	NickName  string `json:"nick_name"`  // 用户名
	Avatar    string `json:"avatar"`     // 用户头像
	CreatedAt int64  `json:"created_at"` // 注册时间
	IsVIP     int64  `json:"is_vip"`     // 1:是  非1: 不是
}

func UserInfo(c *ginHelper.GinCtx) {
	userIdStr := c.Param("userId")
	userId := utils.AnyToInt64(userIdStr)
	user, err := new(dao.UserDao).GetUser(userId)
	if err != nil {
		c.APIOutPutError(err, err.Error())
		return
	}
	c.APIOutPut(&UserInfoData{
		UserId:    user.UserId,
		Account:   user.Account,
		NickName:  user.NickName,
		Avatar:    user.Avatar,
		CreatedAt: user.CreatedAt,
		IsVIP:     user.IsVip,
	}, "ok")
	return
}

// 设置用户为VIP
func UserSetVIP(c *ginHelper.GinCtx) {
	userIdStr := c.GetQuery("user_id")
	userId := utils.AnyToInt64(userIdStr)

	err := new(dao.UserDao).SetVIP(userId)
	if err != nil {
		c.APIOutPutError(err, err.Error())
		return
	}

	c.APIOutPut("ok", "ok")
	return
}

func UserDeleteVIP(c *ginHelper.GinCtx) {
	userIdStr := c.GetQuery("user_id")
	userId := utils.AnyToInt64(userIdStr)

	err := new(dao.UserDao).DeleteVIP(userId)
	if err != nil {
		c.APIOutPutError(err, err.Error())
		return
	}

	c.APIOutPut("ok", "ok")
	return
}

var UserStateMap sync.Map

func GetUserPlayGameTotal() int64 {
	var total int64 = 0
	UserStateMap.Range(func(key, value any) bool {
		stateData := value.(*entity.UserState)
		if stateData.State > 0 {
			total++
		}
		return true
	})
	return total
}

// 设置用户状态
func SetUserState(user int64, stateData *entity.UserState) {
	UserStateMap.Store(utils.AnyToString(user), stateData)
}

// 获取用户状态
func GetUserState(user int64) *entity.UserState {
	stateData := &entity.UserState{}
	data, ok := UserStateMap.Load(utils.AnyToString(user))
	if !ok {
		return stateData
	}
	stateData = data.(*entity.UserState)
	return stateData
}

// 获取用户状态，用于app切后台导致用户离开当前房间或游戏
func UserState(c *ginHelper.GinCtx) {
	userIdStr := c.GetQuery("userId")
	userId := utils.AnyToInt64(userIdStr)

	data := GetUserState(userId)
	c.APIOutPut(data, "ok")
	return
}

// 上传文件接口
func Upload(c *ginHelper.GinCtx) {
	file, err := c.FormFile("file")
	if err != nil {
		c.APIOutPutError(err, err.Error())
		return
	}

	extName := path.Ext(file.Filename)

	allowExtMap := map[string]bool{
		".jpg":  true,
		".png":  true,
		".jpeg": true,
	}

	if _, ok := allowExtMap[extName]; !ok {
		c.APIOutPutError(fmt.Errorf("上传的文件类型不合法"), "上传的文件类型不合法")
		return
	}

	dir := "./img/"

	err = os.MkdirAll(dir, 0666)
	if err != nil {
		c.APIOutPutError(err, err.Error())
		return
	}

	// 4、生成文件名称和文件保存的目录   111111111111.jpeg
	fileName := utils.IDStr() + extName

	// 5、执行上传
	dst := path.Join(dir, fileName)
	err = c.SaveUploadedFile(file, dst)
	if err != nil {
		c.APIOutPutError(err, err.Error())
		return
	}

	hostUrl, err := conf.YamlGetString("hostUrl")
	if err != nil {
		c.APIOutPutError(err, err.Error())
		return
	}

	out := path.Join("/img/", fileName)
	out = hostUrl + out
	c.APIOutPut(out, "ok")
	return
}

// 上传APK
func AddAPK(c *ginHelper.GinCtx) {
	file, err := c.FormFile("apk")
	if err != nil {
		log.Error("FormFile err", err)
		c.APIOutPutError(err, err.Error())
		return
	}
	extName := path.Ext(file.Filename)
	allowExtMap := map[string]bool{
		".apk": true,
	}
	if _, ok := allowExtMap[extName]; !ok {
		c.APIOutPutError(fmt.Errorf("上传的文件类型不合法"), "上传的文件类型不合法")
		return
	}
	// 删除旧文件
	_ = os.Remove("./download/app.apk")

	dst := path.Join("./download", "app.apk")
	err = c.SaveUploadedFile(file, dst)
	if err != nil {
		log.Error("SaveUploadedFile err", err)
		c.APIOutPutError(err, err.Error())
		return
	}

	hostUrl, err := conf.YamlGetString("hostUrl")
	if err != nil {
		c.APIOutPutError(err, err.Error())
		return
	}
	out := hostUrl + "/download/app.apk"
	c.APIOutPut(out, "ok")
	return
}

func AddFile(c *ginHelper.GinCtx) {
	file, err := c.FormFile("file")
	if err != nil {
		log.Error("FormFile err", err)
		c.APIOutPutError(err, err.Error())
		return
	}

	dst := path.Join("./file/", file.Filename)
	err = c.SaveUploadedFile(file, dst)
	if err != nil {
		log.Error("SaveUploadedFile err", err)
		c.APIOutPutError(err, err.Error())
		return
	}

	hostUrl, err := conf.YamlGetString("hostUrl")
	if err != nil {
		c.APIOutPutError(err, err.Error())
		return
	}
	out := hostUrl + "/file/" + file.Filename
	c.APIOutPut(out, "ok")
	return
}

// 用户修改信息
func UserModify(c *ginHelper.GinCtx) {
	userIdStr := c.GetQuery("user_id")
	userId := utils.AnyToInt64(userIdStr)
	nickName := c.GetQuery("nick_name")
	avatar := c.GetQuery("avatar")

	err := new(dao.UserDao).Modify(userId, nickName, avatar)
	if err != nil {
		c.APIOutPutError(err, err.Error())
		return
	}

	c.APIOutPut("ok", "ok")
	return
}

// 测试计算牌结果
func TNiu(c *ginHelper.GinCtx) {
	p := c.GetQuery("p")
	pList := strings.Split(p, ",")

	pData := make([]*entity.PokerData, 0)
	for _, v := range pList {
		pData = append(pData, &entity.PokerData{
			Poker:       v,
			PokerNumber: entity.GetPokerStrNumber(v),
			PokerStr:    v,
			Points:      entity.PokerValue[v], // 点数
		})
	}

	result := new(dao.RuleDao).GetDouNiuResult(pData)

	c.APIOutPut(result, "ok")
	return
}

type TNiuVsRse struct {
	Msg string               `json:"msg"`
	P1  *entity.DouNiuResult `json:"p1"`
	P2  *entity.DouNiuResult `json:"p2"`
}

// 测试比牌
func TNiuVs(c *ginHelper.GinCtx) {
	p1 := c.GetQuery("p1")
	p1List := strings.Split(p1, ",")
	p2 := c.GetQuery("p2")
	p2List := strings.Split(p2, ",")

	p1Data := make([]*entity.PokerData, 0)
	for _, v := range p1List {
		p1Data = append(p1Data, &entity.PokerData{
			Poker:       v,
			PokerNumber: entity.GetPokerStrNumber(v),
			PokerStr:    v,
			Points:      entity.PokerValue[v], // 点数
		})
	}
	p1Result := new(dao.RuleDao).GetDouNiuResult(p1Data)

	p2Data := make([]*entity.PokerData, 0)
	for _, v := range p2List {
		p2Data = append(p2Data, &entity.PokerData{
			Poker:       v,
			PokerNumber: entity.GetPokerStrNumber(v),
			PokerStr:    v,
			Points:      entity.PokerValue[v], // 点数
		})
	}
	p2Result := new(dao.RuleDao).GetDouNiuResult(p2Data)

	bp := new(dao.RuleDao).DouNiuContrast(p1Result, p2Result)
	msg := ""
	if bp {
		msg = fmt.Sprintf("p1赢; p1:%s   p2:%s", entity.PokerToStr(p1Result.Poker), entity.PokerToStr(p2Result.Poker))
	} else {
		msg = fmt.Sprintf("p1输; p1:%s   p2:%s", entity.PokerToStr(p1Result.Poker), entity.PokerToStr(p2Result.Poker))
	}

	c.APIOutPut(&TNiuVsRse{
		Msg: msg,
		P1:  p1Result,
		P2:  p2Result,
	}, "ok")
	return
}

// 测试变牌
func TBianPai(c *ginHelper.GinCtx) {
	niuTypeStr := c.GetQuery("type")
	niuType := utils.AnyToInt64(niuTypeStr)

	// 初始化一幅牌
	poker := entity.NewPoker()

	// 去除10张
	poker = poker[20:len(poker)]

	log.Info("牌数量: ", len(poker))

	// 剩余的牌中生成变牌
	rse, has := new(dao.RuleDao).ChangeDouNiuPoker(poker, niuType)
	if !has {
		c.APIOutPut("", "剩余的牌无法组成这个类型的牌")
		return
	}
	c.APIOutPut(rse, "ok")
	return
}
